\NeedsTeXFormat{LaTeX2e}[2017/04/15]
\RequirePackage{expl3}
\RequirePackage{xparse}
\ProvidesPackage{xdyy-math}
  [2022/03/09 v0.0.7 A LaTeX package for some math needs.]


% 加载宏包
\RequirePackage{tikz}               % 绘图
\RequirePackage{varwidth}           % 最小宽度型的minipage
\RequirePackage{extarrows}          % 箭头
\RequirePackage{enumitem}           % 定制list环境
% \RequirePackage{amssymb}
\RequirePackage{amsthm, thmtools}   % 定义定理环境
\RequirePackage{xcolor}
\RequirePackage[most]{tcolorbox}    % 彩框
\RequirePackage{manfnt}             % 提供“危险”符号
% \RequirePackage{fontsetup}
\RequirePackage[physics]{physicx}

% 加载tikz的库
\usetikzlibrary{calc}               % 相对位置
\usetikzlibrary{
  decorations.pathmorphing,
  decorations.pathreplacing, 
  decorations.shapes
}
\usetikzlibrary{arrows.meta}        % 箭头
\usetikzlibrary{positioning}        % 相对方位


% 加载tcolorbox的库
\tcbuselibrary{hooks}


\ExplSyntaxOn
% 间距
\dim_set:Nn \lineskiplimit { .5em }
\skip_set:Nn \lineskip { .5em }

% 定义定理环境


\declaretheoremstyle
  [
    spaceabove = 6pt,
    spacebelow = 6pt,
    headfont = \normalfont\bfseries,
    notefont = \mdseries, 
    notebraces = {(}{)},
    bodyfont = \ttfamily,
    % bodyfont = \itshape,
    headpunct = {},
    postheadspace = 1em,
  ]
  { withoutcounterstyle }

\cs_new:Npn \__xdyymath_declare_theorem_with_counter:n #1
  {
    \declaretheorem
      [
        name =  \clist_item:nn {#1} {1} ,
        refname = \clist_item:nn {#1} {2} ,
        within = \clist_item:nn {#1} {3} ,
      ]
      { \clist_item:nn {#1} {4} }
  }
\cs_new:Npn \__xdyymath_declare_theorem_without_counter:n #1
  {
    \declaretheorem
      [
        name =  \clist_item:nn {#1} {1} ,
        refname = \clist_item:nn {#1} {2},
        numbered = no,
        % headpunct = {},
        style = withoutcounterstyle
      ]
      { \clist_item:nn {#1} {3} }
  }
\clist_map_function:nN
  {
    { 定义, 定义, section, definition },
    { 定理, 定理, section, theorem },
    { 例, 例, section, example },
    { 性质, 性质, section, property },
    { 命题, 命题, section, proposition },
    { 推论, 推论, section, corollary },
    { 引理, 引理, section, lemma },
    { 公理, 公理, section, axiom },
    { 反例, 反例, section, antiexample },
    { 猜想, 猜想, section, conjecture },
    { 问题, 问题, section, question },
    { 断言, 断言, section, claim },
  }\__xdyymath_declare_theorem_with_counter:n
\clist_map_function:nN
  {
    {
      { \color{ red } \textdbend 注 },
      注,
      remark 
    },
    { { \color{ teal } \mantriangleright 提示 }, 提示, hint },
    { { \color{ red!70!white } \manstar 总结  }, 总结, summary },
    {
      { \color{ -red!75!green!50 }  \manerrarrow 分析 },
      分析,
      analysis 
    }
  }\__xdyymath_declare_theorem_without_counter:n

\tcolorboxenvironment{remark}
  {
    enhanced~jigsaw, 
    parbox = false,
    breakable,
    boxrule = 0.2pt,
    colback = pink!10,
    left = 2mm,
    bottom = 6mm,
    right = 2mm,
    before~skip = 10pt
  }
\ExplSyntaxOff


% 多种方法: method环境
\newlist{method}{enumerate}{1}
\setlist[method, 1]
  {
    label = {\bfseries Method \Roman*.},
    labelindent = !,
    labelwidth  = 1.3cm,
    labelsep*   = 0.5em,
    leftmargin  = 2.2cm
  }
% 分类讨论: case环境
\newlist{case}{enumerate}{2}
\setlist[case, 1]
  {
    label = {\bfseries Case \arabic*.},
    % labelindent=-3em ,labelwidth=1.3cm, labelsep*=1em, leftmargin=20pt
    labelindent = !,
    labelwidth  = 1.3cm,
    labelsep*   = 0.5em,
    leftmargin  = 1.7cm
    % labelindent=\parindent, leftmargin=0pt, widest=0, itemindent=*
  }
\setlist[case, 2]
  {
    label = {\bfseries Subcase \arabic{casei}.\arabic*.},
    % labelindent=-1em ,labelwidth=1.3cm, labelsep*=1em, leftmargin =20pt
    labelindent = -0.5em,
    labelwidth  = 1.3cm,
    labelsep*   = 0.5em,
    leftmargin  = 0cm
  }
% 分步: step环境
\newlist{step}{enumerate}{2}
\setlist[step, 1]
  {
    label = {\bfseries Step \arabic*.},
    labelindent = !,
    labelwidth  = 1.3cm,
    labelsep*   = 0.5em,
    leftmargin  = 1.7cm
    % labelindent=\parindent, leftmargin = 0pt, widest = 0, itemindent = *
  }
\setlist[step, 2]
  {
    label       =  {\bfseries Substep \arabic{stepi}.\arabic*.},
    labelindent = -0.5em,
    labelwidth  = 1.3cm,
    labelsep*   = 0.5em, 
    leftmargin  = 0cm
  }


\ExplSyntaxOn


% 思路推导命令\deduce[<key-value>]{<left>}{<right>}

% leftbrace到arrow的距离
\dim_new:N \l__deduce_leftbrace_to_arrow_dim
% arrow与rightbrace的距离
\dim_new:N \l__deduce_arrow_to_rightbrace_dim
% rightbrace到rightarrow的额外水平移动量
\dim_new:N \l__deduce_rightbrace_to_rightbox_horizontal_distance_dim

\bool_new:N \l__deduce_leftbrace_show_bool
\bool_new:N \l__deduce_rightbrace_show_bool

\tl_new:N \l__deduce_arrow_tl
\tl_new:N \l__deduce_leftbox_align_tl
\tl_new:N \l__deduce_rightbox_align_tl

%%%% 自定义函数，简化代码 %%%%
% \__check_align:n
% 效果：用来实现左右对齐与居中
% 参数：center, left, right其中一个
% 函数编写原因：deduce命令的左右box都是用varwidth环境包裹了，直接用node的align失效了，需要“深入varwidth环境内部”产生对齐效果，但是左右两边的判断是一样的，所以就编写了一个函数来减少代码量

\cs_new:Npn \__check_align:n #1
  {
    \str_case:nn {#1}
      {
        { left }   { \raggedright }
        { right }  { \raggedleft }
        { center } { \centering }
      }
  }
% 产生\__check_align:n的V变体，使得参数可以为tl变量而不是{}
\cs_generate_variant:Nn \__check_align:n {V}
\cs_new:Npn \__check_enumerate_itemize:nnn #1#2#3
  {
    \str_if_in:nnTF {#1} {enumerate}
      {#2}
      {
        \str_if_in:nnTF {#1} {itemize}
        {#2}
        {#3}
      }
  }


\keys_define:nn { xdyy-math / deduce }
  {
    % 中间箭头样式
    arrow .tl_set:N = \l__deduce_arrow_tl,
    arrow .initial:n = $\Longrightarrow$,
    % 左边box的对齐方式
    leftbox-align .tl_set:N = \l__deduce_leftbox_align_tl,
    leftbox-align .initial:n = right,
    % 右边box的对齐方式
    rightbox-align .tl_set:N = \l__deduce_rightbox_align_tl,
    rightbox-align .initial:n = left,
    % 是否显示左边的括号
    show-leftbrace .bool_set:N = \l__deduce_leftbrace_show_bool,
    show-leftbrace .initial:n = true,
    % 是否显示右边的括号
    show-rightbrace .bool_set:N = \l__deduce_rightbrace_show_bool,
    show-rightbrace .initial:n = true,
    % leftbrace到arrow的距离
    leftbrace-to-arrow .dim_set:N = \l__deduce_leftbrace_to_arrow_dim,
    leftbrace-to-arrow .initial:n = 7pt,
    % arrow到rightbrace的距离
    arrow-to-rightbrace .dim_set:N = \l__deduce_arrow_to_rightbrace_dim,
    arrow-to-rightbrace .initial:n = 2pt,
    % rightbrace到rightarrow的额外水平移动量
    rightbrace-to-rightbox .dim_set:N = \l__deduce_rightbrace_to_rightbox_horizontal_distance_dim,
    rightbrace-to-rightbox .initial:n = 3mm,
  }


\NewDocumentCommand { \deduce } { O{} +m +m }
  {
    \group_begin:
      \__check_enumerate_itemize:nnn {#2}
        {
          \bool_set_true:N \l__deduce_leftbrace_show_bool
          \keys_set:nn { xdyy-math / deduce }
            {
              leftbrace-to-arrow = 3.5mm
            }
        }
        {
          \bool_set_false:N \l__deduce_leftbrace_show_bool
          \keys_set:nn { xdyy-math / deduce }
            {
              leftbrace-to-arrow = 1pt
            }
        }
      \__check_enumerate_itemize:nnn {#3}
        {
          \bool_set_true:N \l__deduce_rightbrace_show_bool
        }
        {
          \bool_set_false:N \l__deduce_rightbrace_show_bool
        }
      \keys_set:nn { xdyy-math / deduce } {#1}
      \begin{tikzpicture}
        \node [] (leftbox)
          {
            \begin{varwidth}{\hsize}
              % 内部产生对齐效果
              \__check_align:V \l__deduce_leftbox_align_tl
              #2
            \end{varwidth}
          };
        \node[right = \l__deduce_leftbrace_to_arrow_dim~of~leftbox] (arrow)
          {
            \tl_use:N \l__deduce_arrow_tl
          };
        \node
          [
            right = \l__deduce_arrow_to_rightbrace_dim~of~arrow,
            % draw
          ] (rightbox)
          {
            \begin{varwidth}{\hsize}
              % 内部产生对齐效果
              \__check_align:V \l__deduce_rightbox_align_tl
              #3
            \end{varwidth}
          };
        \bool_if:NT \l__deduce_leftbrace_show_bool
          {
            \draw
              [
                decorate,
                decoration = { brace, amplitude = 5pt }
              ]
              (leftbox.north~east) -- (leftbox.south~east) ;
          }
          \bool_if:NT \l__deduce_rightbrace_show_bool
          {
            \draw
              [
                decorate,
                decoration = { brace, mirror, amplitude = 5pt},
              ]
              ([xshift = \l__deduce_rightbrace_to_rightbox_horizontal_distance_dim]rightbox.north~west) -- ([xshift = \l__deduce_rightbrace_to_rightbox_horizontal_distance_dim]rightbox.south~west) ;
          }
      \end{tikzpicture}
    \group_end:
  }


% overlay命令，实现符号叠加


\keys_define:nn { xdyy-math / overlay }
  {
    % 内容
    below-label .tl_set:N = \l__xdyymath_overlay_below_label_tl,
    below-label .initial:n = {$\Longleftrightarrow$},
    above-label .tl_set:N = \l__xdyymath_overlay_above_label_tl,
    above-label .initial:n = {?},
    % 颜色
    below-color .tl_set:N = \l__xdyymath_overlay_below_color_tl,
    below-color .initial:n = black,
    above-color .tl_set:N = \l__xdyymath_overlay_above_color_tl,
    above-color .initial:n = black,
    % anchor
    below-anchor .tl_set:N = \l__xdyymath_overlay_below_anchor_tl,
    below-anchor .initial:n = south,
    above-anchor .tl_set:N = \l__xdyymath_overlay_above_anchor_tl,
    above-anchor .initial:n = base,
    % 移动
    below-vsep .dim_set:N = \l__xdyymath_overlay_below_vsep_dim,
    below-vsep .initial:n = 0pt,
    above-vsep .dim_set:N = \l__xdyymath_overlay_above_vsep_dim,
    above-vsep .initial:n = 0pt,
    below-hsep .dim_set:N = \l__xdyymath_overlay_below_hsep_dim,
    below-hsep .initial:n = 0pt,
    above-hsep .dim_set:N = \l__xdyymath_overlay_above_hsep_dim,
    above-hsep .initial:n = 0pt,
    % 整体移动
    vsep .dim_set:N = \l__xdyymath_overlay_vsep_dim,
    vsep .initial:n = 0pt,
    % scale
    below-scale .fp_set:N = \l__xdyymath_overlay_below_scale_fp,
    below-scale .initial:n = 1,
    above-scale .fp_set:N = \l__xdyymath_overlay_above_scale_fp,
    above-scale .initial:n = 1,
  }


\NewDocumentCommand { \overlay } { O{} }
  {
    % “吃掉前面的空格”
    \unskip
    \group_begin:
      \c_space_tl
      \keys_set:nn { xdyy-math / overlay } {#1}
      \begin{tikzpicture}
        [
          baseline = 
            { ( [ yshift = - \l__xdyymath_overlay_vsep_dim ]current~bounding~box.base ) },
          inner~sep = 0pt, outer~sep = 0pt
        ]
        \node
          [
            anchor = \l__xdyymath_overlay_below_anchor_tl,
            scale = \fp_use:N \l__xdyymath_overlay_below_scale_fp
          ]
          at
          (
            \dim_use:N \l__xdyymath_overlay_below_hsep_dim,
            \dim_use:N \l__xdyymath_overlay_below_vsep_dim
          )
          {
            \group_begin:
              \color { \l__xdyymath_overlay_below_color_tl }
              \l__xdyymath_overlay_below_label_tl
            \group_end:
          };
        \node
          [
            anchor = \l__xdyymath_overlay_above_anchor_tl,
            scale = \fp_use:N \l__xdyymath_overlay_above_scale_fp
          ]
          at
          (
            \dim_use:N \l__xdyymath_overlay_above_hsep_dim,
            \dim_use:N \l__xdyymath_overlay_above_vsep_dim
          )
          {
            \group_begin:
              \color { \l__xdyymath_overlay_above_color_tl }
              \l__xdyymath_overlay_above_label_tl
            \group_end:
          };
      \end{tikzpicture}
      \c_space_tl
    \group_end:
    % “吃掉后面的空格”
    \ignorespaces
  }


% 定义充分必要性环境

% 必要性
\NewDocumentEnvironment { necessity } { +b }
  {
    \par \noindent
    \framebox
      {
        $
          \xLongrightarrow
          { \text { \normalsize 必要性 } }
        $ 
      }
    \par \addvspace{ .5em plus .5em minus .2em }
    \par #1
    \par \addvspace{ .5em plus .5em minus .2em }
  }
  {}

% 充分性
\NewDocumentEnvironment { sufficiency } { +b }
  {
    \par \noindent 
    \framebox
      {
        $
          \xLongleftarrow 
          { \text{ \normalsize 充分性 } }
        $ 
      }
    \par \addvspace{ .5em plus .5em minus .2em }
    \par #1
    \par \addvspace{ .5em plus .5em minus .2em }
  }
  {}


\NewDocumentEnvironment { existence } { +b }
  {
    \par \noindent
    （存在性）
    \par \addvspace{ .5em plus .5em minus .2em }
    \par #1
    \par \addvspace{ .5em plus .5em minus .2em }
  }
  {}

\NewDocumentEnvironment { uniqueness } { +b }
  {
    \par \noindent
    （唯一性）
    \par \addvspace{ .5em plus .5em minus .2em }
    \par #1
    \par \addvspace{ .5em plus .5em minus .2em }
  }
  {}


% 定义数学符号
\cs_new:Npn \__xdyymath_newcommand:Nn #1#2 { \newcommand {#1} {#2} }
\cs_generate_variant:Nn \__xdyymath_newcommand:Nn { c }
\AtBeginDocument
  {
    \IfPackageLoadedTF { unicode-math }
      {
        \cs_set_eq:NN \__xdyymath_mathbb:n \symbb
        \cs_set_eq:NN \__xdyymath_mathcal:n \symcal
        \cs_set_eq:NN \__xdyymath_mathscr:n \symscr
        \cs_set_eq:NN \__xdyymath_mathrm:n \symrm
        % 数学字体
        \setmathfont{NewCMMath-Book.otf}[]
        \setmathfont{XITSMath-Regular.otf}[range={"02205}]	% 将空集符号字体设置为 XITS
      }
      {
        % \RequirePackage { unicode-math } 
        \cs_set_eq:NN \__xdyymath_mathbb:n \mathbb
        \cs_set_eq:NN \__xdyymath_mathcal:n \mathcal
        \cs_set_eq:NN \__xdyymath_mathscr:n \mathscr
        \cs_set_eq:NN \__xdyymath_mathrm:n \mathrm
        % \cs_set_eq:NN \__xdyymath_mathbb:n \symbb
        % \cs_set_eq:NN \__xdyymath_mathcal:n \symcal
        % \cs_set_eq:NN \__xdyymath_mathscr:n \symscr
      }
  }

\cs_set:Npn \__xdyymath_math_symbol_new_mathbb:n #1
  {
    \__xdyymath_newcommand:cn {#1}
      {
        \ensuremath
          { \__xdyymath_mathbb:n {#1} }
      }
  }
\cs_set:Npn \__xdyymath_math_symbol_new_mathcal:n #1
  {
    \__xdyymath_newcommand:cn { cal #1 }
      {
        \ensuremath
          { \__xdyymath_mathcal:n {#1} }
      }
  }
\cs_set:Npn \__xdyymath_math_symbol_new_mathsrc:n #1
  {
    \__xdyymath_newcommand:cn { scr #1 }
      {
        \ensuremath
          { \__xdyymath_mathscr:n {#1} }
      }
  }

% 定义mathbb类符号
\clist_map_function:nN
  {
    A, B, C, D, E, F, G, I, J,
    K, M, N, Q, R, T,
    U, V, W, X, Y, Z
  }
  \__xdyymath_math_symbol_new_mathbb:n

% 定义mathcal类符号
\clist_map_function:nN
  {
    A, B, C, D, E, F, G, H, I, J,
    K, L, M, N, O, P, Q, R, S, T,
    U, V, W, X, Y, Z
  }
  \__xdyymath_math_symbol_new_mathcal:n

% 定义mathscr类符号
\clist_map_function:nN
  {
    A, B, C, D, E, F, G, H, I, J,
    K, L, M, N, O, P, Q, R, S, T,
    U, V, W, X, Y, Z
  }
  \__xdyymath_math_symbol_new_mathsrc:n


% 重定义命令

% 强调 emph
\keys_define:nn { xdyy-math / emph }
  {
    color .tl_set:N = \l__xdyymath_emph_math_color_tl,
  }
\RenewDocumentCommand { \emph } { O{} m }
  {
    \group_begin:
      \if_mode_math:
        \tl_set:Nn \l__xdyymath_emph_math_color_tl
          { red!80 }
      \else:
        \tl_set:Nn \l__xdyymath_emph_math_color_tl
          { black }
      \fi:
      \keys_set:nn { xdyy-math / emph } {#1}
      \color{ \l__xdyymath_emph_math_color_tl }
      \if_mode_math:
        #2
      \else:
        \itshape #2
      \fi:
    \group_end:
  }

% \text 命令，让两边增加一点间距

% \cs_set_eq:NN \__xdyymath_text:n \text

% \RenewDocumentCommand { \text } { m }
%   {
%     \, \__xdyymath_text:n {#1} \,
%   }

% 简化命令

% 集合 set
\NewDocumentCommand { \set } { +m +m }
  {
    \left\{ \,\, #1 :  #2 \, \right\} 
  }

% 使得 such that: s.t.
\NewDocumentCommand { \st } { }
  {
    \if_mode_math: 
      \text { \,\, s.t. \,\, }
    \else:
      \, s.t. \,\,
    \fi
  }

% 几乎处处 almost everywhere: a.e.
\DeclareDocumentCommand { \ae } { }
  {
    \if_mode_math: 
      \text { \,\, a.e. \,\, }
    \else:
      \, a.e. \,\,
    \fi
  }

% 也就是说 i.e.
\NewDocumentCommand { \ie } { }
  {
    \if_mode_math: 
      \text { \,\, i.e. \,\, }
    \else:
      \, i.e. \,\,
    \fi
  }


% "定义"符号 := 与=: 与 =上有个delta
\NewDocumentCommand { \coloneq } { } { := }
\NewDocumentCommand { \eqcolon } { } { =: }
\NewDocumentCommand { \deltaeq } { } { \xlongequal{\Delta} }


% 一些箭头
\NewDocumentCommand { \so } { } { \ensuremath { \implies } } 
\cs_set:Nn \iff: { \ensuremath  { \Longleftrightarrow } }
\cs_set_eq:NN \iff \iff:

% 一些集合
\RenewDocumentCommand { \emptyset } { } { \ensuremath { \varnothing } }
% \NewDocumentCommand { \Rn } { } { \ensuremath { \symbb{R}^n } }
\NewDocumentCommand { \Rm } { } { \ensuremath { \symbb{R}^m } }
\NewDocumentCommand { \Rk } { } { \ensuremath { \symbb{R}^k } }
\NewDocumentCommand { \Cn } { } { \ensuremath { \symbb{C}^n } }
\NewDocumentCommand { \Cm } { } { \ensuremath { \symbb{C}^m } }
\NewDocumentCommand { \Ck } { } { \ensuremath { \symbb{C}^k } }
% \NewDocumentCommand {  } { } {  }
% \NewDocumentCommand {  } { } {  }

\AtBeginDocument
  {
    % \RenewDocumentCommand { \closure } { m } { \overline{ \ensuremath{#1} } }
    \NewDocumentCommand { \closure } { m } { \overline{ \ensuremath{#1} } }
  }


% 一些运算
\NewDocumentCommand { \lrangle } { m m }
  { \ensuremath { \langle #1,~#2 \rangle } }
\cs_set_eq:NN \innerproduct \lrangle
\NewDocumentCommand { \pie } { } { ^{ \prime } }    % 撇 '
\NewDocumentCommand { \conjugate } { m } { \overline{ \ensuremath{#1} } }    % 共轭
\cs_set_eq:NN \leq \leqslant
\cs_set_eq:NN \geq \geqslant

% 一些operator
\cs_set_eq:NN \__xdyymath_declare_math_operator:Nn \DeclareMathOperator
\cs_generate_variant:Nn \__xdyymath_declare_math_operator:Nn { cn }
% 不变的类型，比如\diam: diam
\cs_new:Npn \__xdyymath_declare_math_operator_same:n #1
  {
    \__xdyymath_declare_math_operator:cn { #1 } { #1 }
  }
% 变成首字母大写的
\cs_new:Npn \__xdyymath_declare_math_operator_titlecase:n #1
  {
    \__xdyymath_declare_math_operator:cn { #1 } 
      { 
        % \str_uppercase:f { \tl_head:n {#1} } 
        % \tl_tail:n {#1}
        \text_titlecase:n { #1 }
      }
  }

% 全小写的
\clist_map_function:nN
  {
    diam, supp, sgn, codim,
  }
  \__xdyymath_declare_math_operator_same:n

% 首字母大写的
\clist_map_function:nN
  {
    cont
  }
  \__xdyymath_declare_math_operator_titlecase:n


% 一些特殊处理的
\__xdyymath_declare_math_operator:Nn \Span { span }
\__xdyymath_declare_math_operator:Nn \image { Im }
\__xdyymath_declare_math_operator:Nn \kernel { Ker }
\AtBeginDocument
  {
    \RenewDocumentCommand { \Re } { } { \operatorname {Re} }
    \RenewDocumentCommand { \Im } { } { \operatorname {Im} }
  }

% 一些常量
\NewDocumentCommand { \e } { } { \__xdyymath_mathrm:n { e } }
\RenewDocumentCommand { \i } { } { \__xdyymath_mathrm:n { i } }
\AtBeginDocument
  {
    \tl_set_eq:NN \l__xdyymath_pi_tl { \pi }
    \tl_set:Nn \pi { \__xdyymath_mathrm:n { \l__xdyymath_pi_tl } }
  }


\ExplSyntaxOff